範圍(或作用域、範疇),代表各個識別項(變數跟函式)可以在那些位置被使用。
其實官方文檔用的詞叫字彙環境(Lexical Environment),上面幾個是比較俗稱的叫法,
來看一下官方文檔對字彙環境的說明
![
我也聽不懂,還是直接看程式吧(
var str = '全域變數的str';
var scope = 'Global';
function funcA() {
var str = 'funcA內的str';
var scope = 'A';
function funcB() {
var scope = 'B';
console.log('funcB找到的scope: ' + scope);
console.log('funcB找到的str: ' + str);
}
funcB();
funcC();
}
function funcC() {
var scope = 'C';
console.log('funcC找到的str:' + str);
}
funcA();
JavaScript會依照程式碼的位置來建構字彙環境(下圖用背景顏色區分不同字彙環境)
最外部的字彙環境(紅色)的為全域字彙環境,每當有函式被宣告時,就會在內部產生新的字彙環境(藍綠紫色),
像在funcA
內建立了funcB
,此時funcA
為funcB
的外部環境,funcA
的外部環境為全域字彙環境,
深色的點為該字彙環境內的識別項。
換個角度畫圖,上到下是由內部環境到外部環境
當想要存取變數或呼叫函式時,會在目前的字彙環境內尋找是否有該識別項,
目前環境沒有此識別項的話,就往外部環境一層一層找,直到找到識別項。
這種一層一層的關係就叫做範圍鍊
(scope chain)
另外這種查找只能由內到外,外部是沒辦法存取內部環境的識別項。
懂甚麼是範圍鍊後,現在來用範圍鍊來解釋上面的程式
程式碼在funcA
內呼叫了funcB
,funcB
需要scope
跟str
兩個的值來印出,funcB
在自己的字彙環境內找到scope
變數得到'B'
值,但找不到str
變數,
依範圍鍊往外部環境的funcA
的環境查找,找到funcA
內的str
變數成功取值。
接著呼叫funcC
印出str
,funcC
一樣在自己的字彙環境找不到str
變數,funcC
的外部環境是全域字彙環境,會在全域字彙環境找到str
值後印出。
由此例子可以看出範圍鍊只跟程式碼寫的位置有關,
即使funcC
跟funcB
一樣是在funcA
內被呼叫的,還是會取得不同的str
值
執行結果:
都畫糞解說圖了字還是好多,累